﻿using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace Labthink.PCSoft.UniversalHost4.UserControls
{
    public partial class CheckboxTreeView
    {
        /// <summary>
        /// 控件数据
        /// </summary>
        private ObservableCollection<TreeNodeModel> _itemsSourceData;

        /// <summary>
        /// 构造
        /// </summary>
        public CheckboxTreeView()
        {
            InitializeComponent();
            DataContext = this;
        }

        /// <summary>
        /// 控件数据
        /// </summary>
        public ObservableCollection<TreeNodeModel> ItemsSourceData
        {
            get => _itemsSourceData;
            set
            {
                _itemsSourceData = value;
                cbTree.ItemsSource = _itemsSourceData;
            }
        }

        public void RefreshCheckStatus()
        {
            var leaves = GetLeafNodes();
            foreach (var item in leaves)
            {
                item.SetParentChecked();
            }
        }

        /// <summary>
        /// 设置对应Id的项为选中状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="treeList"></param>
        /// <returns></returns>
        public int SetCheckedById(string id, ObservableCollection<TreeNodeModel> treeList)
        {
            foreach (var tree in treeList)
            {
                if (tree.Id.Equals(id))
                {
                    tree.IsChecked = true;
                    return 1;
                }

                if (SetCheckedById(id, tree.Children) == 1)
                {
                    return 1;
                }
            }

            return 0;
        }

        /// <summary>
        /// 设置对应Id的项为选中状态
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public int SetCheckedById(string id)
        {
            foreach (var tree in ItemsSourceData)
            {
                if (tree.Id.Equals(id))
                {
                    tree.IsChecked = true;
                    return 1;
                }
                if (SetCheckedById(id, tree.Children) == 1)
                {
                    return 1;
                }
            }

            return 0;
        }

        /// <summary>
        /// 获取选中项
        /// </summary>
        /// <returns></returns>
        public ObservableCollection<TreeNodeModel> GetCheckedItems()
        {
            return GetCheckedItemsIgnoreRelation(_itemsSourceData);
        }

        /// <summary>
        /// 私有方法，忽略层次关系的情况下，获取选中项
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        private ObservableCollection<TreeNodeModel> GetCheckedItemsIgnoreRelation(ObservableCollection<TreeNodeModel> list)
        {
            var treeList = new ObservableCollection<TreeNodeModel>();
            foreach (var tree in list)
            {
                if (tree.IsChecked != false)
                {
                    treeList.Add(tree);
                }

                foreach (var child in GetCheckedItemsIgnoreRelation(tree.Children))
                {
                    treeList.Add(child);
                }
            }

            return treeList;
        }

        /// <summary>
        /// 获取所有项
        /// </summary>
        /// <returns></returns>
        public ObservableCollection<TreeNodeModel> GetAllNodes()
        {
            return GetAllNodes(_itemsSourceData);
        }

        /// <summary>
        /// 获取所有叶子项
        /// </summary>
        /// <returns></returns>
        public ObservableCollection<TreeNodeModel> GetLeafNodes()
        {
            var all = GetAllNodes(_itemsSourceData);
            var leaves = all.Where(n => n.IsLeaf);
            return new ObservableCollection<TreeNodeModel>(leaves);
        }

        /// <summary>
        /// 获取所有选中的叶子项
        /// </summary>
        /// <returns></returns>
        public ObservableCollection<TreeNodeModel> GetCheckedLeafNodes()
        {
            var all = GetAllNodes(_itemsSourceData);
            var leaves = all.Where(n => n.IsLeaf && n.IsChecked == true);
            return new ObservableCollection<TreeNodeModel>(leaves);
        }

        /// <summary>
        /// 私有方法，忽略层次关系的情况下，获取所有项
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        private ObservableCollection<TreeNodeModel> GetAllNodes(ObservableCollection<TreeNodeModel> list)
        {
            var treeList = new ObservableCollection<TreeNodeModel>();
            foreach (var tree in list)
            {
                treeList.Add(tree);

                foreach (var child in GetAllNodes(tree.Children))
                {
                    treeList.Add(child);
                }
            }

            return treeList;
        }

        /// <summary>
        /// 选中所有子项菜单事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuSelectAllChild_Click(object sender, RoutedEventArgs e)
        {
            if (cbTree.SelectedItem != null)
            {
                TreeNodeModel tree = (TreeNodeModel)cbTree.SelectedItem;
                tree.IsChecked = true;
                tree.SetChildrenChecked(true);
            }
        }

        /// <summary>
        /// 全部展开菜单事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuExpandAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (TreeNodeModel tree in cbTree.ItemsSource)
            {
                tree.IsExpanded = true;
                tree.SetChildrenExpanded(true);
            }
        }

        /// <summary>
        /// 全部折叠菜单事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuUnExpandAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (TreeNodeModel tree in cbTree.ItemsSource)
            {
                tree.IsExpanded = false;
                tree.SetChildrenExpanded(false);
            }
        }

        /// <summary>
        /// 全部选中事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuSelectAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (TreeNodeModel tree in cbTree.ItemsSource)
            {
                tree.IsChecked = true;
                tree.SetChildrenChecked(true);
            }
        }

        /// <summary>
        /// 全部取消选中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuUnSelectAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (TreeNodeModel tree in cbTree.ItemsSource)
            {
                tree.IsChecked = false;
                tree.SetChildrenChecked(false);
            }
        }

        /// <summary>
        /// 鼠标右键事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) is TreeViewItem item)
            {
                item.Focus();
                e.Handled = true;
            }
        }

        static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
        {
            while (source != null && source.GetType() != typeof(T))
                source = VisualTreeHelper.GetParent(source);

            return source;
        }

        private void treeNode_Click(object sender, RoutedEventArgs e)
        {
            if (VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) is TreeViewItem item)
            {
                item.Focus();
                if (cbTree.SelectedItem != null)
                {
                    TreeNodeModel tree = (TreeNodeModel)cbTree.SelectedItem;
                    tree.SetChildrenChecked();
                    tree.SetParentChecked();
                }

                e.Handled = true;
            }
        }
    }
}
